{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "70fb125e-abdb-4859-8981-c4d476108e1e",
   "metadata": {},
   "source": [
    "### 代码练习：用KNN识别数字（最佳K）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "40f016db-c191-4688-a461-784195d5b7a3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当K= 10 的时候此knn模型的准确率为 0.9833333333333333\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#参考\n",
    "\n",
    "from sklearn.datasets import load_digits\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.model_selection import train_test_split\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 1. 获取X和y\n",
    "df = load_digits(as_frame=True).frame\n",
    "X = df.drop('target',axis=1).values\n",
    "y = df['target']\n",
    "\n",
    "# 2. train_test_split\n",
    "X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.30)\n",
    "\n",
    "# 3. 创建KNN模型\n",
    "K=10\n",
    "knn = KNeighborsClassifier(n_neighbors=K)\n",
    "knn.fit(X_train,y_train)\n",
    "\n",
    "# 4. 获得算法的准确率\n",
    "acc=knn.score(X_test,y_test) \n",
    "print(\"当K=\",K,\"的时候此knn模型的准确率为\",acc)\n",
    "\n",
    "# 制作一个3的图像\n",
    "d = np.array(\n",
    "    [[0,0,255,255,255,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,255,255,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,255,255,255,255,0,0]]\n",
    ")\n",
    "\n",
    "\n",
    "plt.imshow(d,cmap='gray')\n",
    "plt.title(str(knn.predict([d.ravel()])),size=20)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5e6d0975-0dc5-4691-b54c-31a598dc17cb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "处理进度: 100%:  ▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋"
     ]
    }
   ],
   "source": [
    "#参考：显示进度条\n",
    "\n",
    "import sys,time\n",
    "def progress_bar(i):\n",
    "    '''持续调用此函数，并传入i，就可以显示基于i的进度的进度条'''\n",
    "    print(\"\\r\", end=\"\")  # 输出位置回到行首\n",
    "\n",
    "    # 显示进度百分比，并同时显示进度1/2(可以自己调节)个数的进度条符号：▋\n",
    "    print(\"处理进度: {}%: \".format(i), \"▋\" * (i // 2), end=\"\")\n",
    "    \n",
    "    # 有的时候大循环中printout不会马上运行，而是等代码运行结束后再依次运行\n",
    "    # 这样有可能让我们的进度条显示异常，所以\n",
    "    # 用flush强制输出,确保以上print语句运行\n",
    "    sys.stdout.flush()  \n",
    "    \n",
    "    time.sleep(0.05) # 程序暂停0.05秒\n",
    "\n",
    "\n",
    "for i in range(0, 101):\n",
    "    progress_bar(i)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cf8273de-799f-453e-a4e2-a0726eafe16e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1797, 8, 8)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x216 with 20 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#参考：载入数据集\n",
    "\n",
    "from sklearn.datasets import load_digits\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "digits = load_digits(n_class=10) # 把十个类（0~9）的数字全部载入\n",
    "print((digits.images).shape) #一共1797层，8*8 的image\n",
    "\n",
    "# 显示前20个数字\n",
    "fg, ax=plt.subplots(1,20,figsize=(20,3))\n",
    "for i in range(20):\n",
    "    ax[i].imshow(digits.images[i],cmap='gray')\n",
    "    ax[i].set(xticks=[], yticks=[])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b4ab0ace-952f-4a36-827d-041f494b60f3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAc8AAAHECAYAAABfv6HoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAABKuUlEQVR4nO3dfWxVZb4v8O+eljJUoCBvCoW+wEytgOVV9Fy14BE1yKgIeuTopBS8mBNyUzAmmJzcYGMyogmp9WVyOZMbhqtXOM6JAscRz/BSisPIMBXolYgdHFrkRRGYikALpWXfPx7Qwv79cP/atfZaXXw/SYM8LPd+nv2stZ691vr2eWLxeBxERESUvJ8EXQEiIqKuhoMnERGREQdPIiIiIw6eRERERhw8iYiIjNItG/fv3z+em5ub9PaNjY1i+aFDhxLKevfuLW6bnZ0tlqelpSVdj4aGBhw/fjyWzLbWNmrq6uoSytra2sRtBw8eLJb36dMn6fcLoo2nTp1KKPvb3/4mbtujRw+xvKCgIOn387ONX3/9tVh++PDhhLKMjAxx25tvvlksD/u+Ku2X9fX14rYjRozo9Pv52UbpuAOA7t27J5R58dlpwn7O0fZVCz/bePToUbFcas+3334rbtvc3CyWa8fj6NGjE8q+/PJLnDhxQmyjafDMzc1FTU1N0tv/7ne/E8sXL16cUDZ16lRx26VLl4rlffv2TboeEyZMSHpbaxs1kydPTijTOrm8vFwsf+ihh5J+vyDauGXLloSyhx9+WNx2zJgxSb+Gxs82vvTSS2L5c889l1A2ZMgQcdvNmzeL5WHfV6X9cs6cOeK2a9as6fT7+dlG6bi79DpX+u1vf5v061qF/Zzjxfv52cZXXnlFLJfao+2TtbW1YnnPnj3F8qqqqoSyKVOmiNsCvG1LRERkxsGTiIjIiIMnERGREQdPIiIiI1NgyEoKBgFykk9L5l5//fVi+TvvvCOWP/roo0nWzl9SUra6ulrcVnpQDdgCQ37avXu3WC49TM/KyhK3bWho8LBGHScFgAB9f1q+fHlC2dNPPy1u+8knn4jl99xzT5K1C4YUnNECXmGn7WfSsbdy5Upx25ycHNNrp9ratWvFcqmNS5Ys8bs6KSWdV7VwkSV0pL321ZLyvPIkIiIy4uBJRERkxMGTiIjIiIMnERGREQdPIiIiI0/StlrKUJsfU5r/ND8/X9xWm7ZPe89Up221JKpl2rmwJxu16a+KiooSyrTp+bQpCFNt/vz5YrmWDB8/fnxCWV5enrht2FO1WspQStsuXLhQ3NaaOPVz/liJNh/0gQMHEsq0ZLg2xZ8lpeknS4JWOx7DTtv/JM8//7xYru2rlnPz1fDKk4iIyIiDJxERkREHTyIiIiMOnkREREYcPImIiIw8Sdtq89KOGzdOLNeStRIp7RgEbZ5ELel18uTJpF9bS/eFhZZ8k5KU2rZhmadX2/f2798vlkuJcS1Vqx0HlsWw/aQt/iylErXFsLX+1RKn2vHhFy3dKy2MrB2jWvo91alajZb6ldLvYU/ya8lXSyJWOzdrtN8e0PZ5Da88iYiIjDh4EhERGXHwJCIiMuLgSUREZORrYEibWs+L1051CEMLSmgPmS310wIAqabVQ3sgrz14l2hhlbDQgkR///vfE8q0wJBWvnHjRrHcr31YWyx50aJFYnlJSUnSr11ZWSmWr1ixIunX8JO2T0oBFG1qTe1z0limkvOCdpxKYSnt2NWm7Uv1dIra+3kx7am2L3gV0OSVJxERkREHTyIiIiMOnkREREYcPImIiIw4eBIRERl5krbVUoPagtUSLVVbU1Mjlj/22GNJv3bYacmyVE+tpU2lpiUsJVrCLSxTm1lJ+7aWnn366afF8pdeekksX7p0accrdhXaIs9a+cqVKxPKtH1SE/ZFl71IWFoXAveLllCtrq5OKNOSuVqieNeuXWK5X+cirS3aeSQWiyW9rd/TnvLKk4iIyIiDJxERkREHTyIiIiMOnkREREYcPImIiIw8Sdtq84JqSdnf/e53SZVdzeLFi03b04/T5unV5pOUFhjWUpfaYtilpaWm7f3y3HPPieXSfLVaMnzDhg1ieaqT4VrKUEteSsla7TW0eXDDkqbW5vWVksbWhbrDkijWjlMpQaulWbXksJZcTXXyX5svWOrH4uJin2sj45UnERGRUecGzw8/BAoKMHTKFGT9r//lUZVCZO5cYOBAYNSooGvin4MHgSlTgMJCFMycif5vvx10jbx39ixw661AUREwciSwZEnQNfJHWxswdiwwfXrQNfFPbi4wejQwZgwwYULQtfHHt98Cs2YBN90EFBYCH38cdI28VVfn+u/ST+/egLL6S5h1fPBsawMWLADWr8fB//ov9PzP/0S3ffs8rFoIzJnjviBEWXo6sGwZsHcv9v2f/4P+//7v6P63vwVdK2917w5s3gzU1gK7d7s+3b496Fp5r7LSnWyjrqrK9aPyWKjLKysD7r8f+Pxzt89GrU8LClz/7d4NfPIJkJkJzJgRdK3MOj547tgBjBgB5OcDGRk4M306rlNmXumy7roLuP76oGvhrxtvBMaNAwBcuO46nMvLQ7djxwKulMdiMaBnT/ff58+7H2Gmki7t0CHg978Hnnoq6JpQZ3z3HbB1KzBvnvt7RgYQkufJvti0CRg+HMjJCbomZh0fPA8fBoYO/f6vrTfcgLSjR72oEwUk48gR9KirQ1MUb1O3tblbRAMHAlOnApMmBV0jby1cCLz8MvCTiMcYYjHg3nuB8eOBf/u3oGvjvf37gQEDgNJSdwv+qaeAM2eCrpV/Vq8GZs8OuhYd0vG0bTz+/X/m5+e7k1JWFrLaJW+1OT2lpOwE5fmFZX7cIGgpQyktqiUBtTSrlqrzxenTuPl//k/gjTdwyx13XPZP2jynUrmWYNTarqUBPU/bpqW520TffutuEe3Zc9mzbG1+5vnz5yf9Flqqdvny5Zaa2r3/vjv+xo8HlH3paqR9+OTJk+K2Kd0nJdu2AYMHA998474E3XSTu0N0UVVVlfi/WeZn1hLFfs+VCgBobQV27gRee819wSsrA5YuBV544ftNtD6QErS//e1vxW21tqQ0UdzSAqxbB7z4YsI/aedEaR7moJLeHf+amp3twiaXHDrkdmrqes6fB2bOBJ54AnjkkaBr468+fYDJk6P1LHvbNncSys0FHn/cPd998smga+WPS+eYgQPdl6AdO4Ktj9eys93PpTsjs2a5wTSK1q93j4wGDQq6Jh3S8cFz4kRg3z6gvt59g1i9GnjwQQ+rRikRj7vnK4WFwDPPBF0bfxw75q44AaC5Gdi40V2xRMWLL7ovrw0N7ji8+27grbeCrpX3zpwBTp364b//8IfoJeFvuME9Dqurc3/ftAm4+eZg6+SXVau67C1boDO3bdPTgddfB+67zz1PmjvX/RpAlMye7W6DHT/uvg2Wl//wID8qtm0D3nzzh/g/APzqV8C0aYFWy1NffQWUlLj99MIF4LHHov3rHFF19OgPqczWVuCf/9mlUqPmtdfcXaCWFhfIXLEi6Bp5r6kJ2LAB8PuRho86N8PQtGnROsleadWqoGvgvzvuuOz5dSTdcgugrFMYOZMnu58oys93v7oRdWPGRPfXcC7JzAROnAi6Fp0S8WgeERGR92Jxw1VHLBY7BuCAf9XxTU48Hh+QzIZsY6ixje2wjaHGNrYTxTaaBk8iIiLibVsiIiIzDp5ERERGHDyJiIiMOHgSEREZcfAkIiIy4uBJRERkxMGTiIjIyDQ9X//+/ePaElKSg+1XXWnn20uTdLfTr18/cdtByoz7aWlpSdejoaEBx48fT2r1Y2sbv/jiC7G8ra0toaygoCDp17Xys41SWwDgyJEjCWUnlCm3el5ajPoKI0aMSLoefrbR4tNPPxXLtX1S63dpez/bKB13AHBUWIdX6xfLcafxoo0tLS3i9lJbAHm/1NqiLXGlnaMyMzMTyoLYV6Xj8ZtvvhG3HT16tFie6vOqZZ8E5HNRc3NzMlX4ntb2jIyMhLKrtdE0eObm5qLGMOfiwoULxfI1a9YklGlr1GmvYVnDTVsrVGJto7b+nbRTaGvUecHPNmo7uLR2p3X9QGlf0PjZRgvtRKftk9oak9L2frZRW1O1oqIioUzrFy/WTvSijdLalQDwyiuviOXSfqm1RTumtXPUmEsLKrQTxL4qHY/a52HZJzVetNGyTwLyuajWON/xunXrxHLpuL5aG3nbloiIyIiDJxERkREHTyIiIqPOref5I3bv3p30ttqzMu05oZ/PDyXaMxbtnr0kFpOfrRcVFYnlls/PT9qzHqntS5YsEbfV+lcr194z1aQ2HjggLw6hlWvPjL14fmhRUlKSdD20ftEyCKmmHY/aeUGqt9YvlZWVYrnWX9IzTz9p9Zb6zBpESvW+ukJZ6Lu6ulosz8rKSijTzjlazsKrICGvPImIiIw4eBIRERlx8CQiIjLi4ElERGTEwZOIiMjI17StlkKT0k5auk9LeWmpOi1h1VlaCk1TXFycUKalvFKdHNZYE8VSelOa5QTQP7+wJIo1ZWVlSW8r9TngXbqvsyz7nzbLTljSttpxru1P0vlF21elRCegfyappvWBdIxpM0Vp+4IXM4FZaGOE1o/S9l7MQtcRvPIkIiIy4uBJRERkxMGTiIjIiIMnERGREQdPIiIiI1/Tttr8pGPHjk0o05KeWmIq1QlG6/tJ6TTL2p9BsKbTLPPPpnoeV432WWuJPW2+2jDTjiUt2Sj1jfYaXZUlLaolPVN9ztHW4ly5cqVYLq2BqdX55MmTYnmq5+nVWOaP1urs9z7MK08iIiIjDp5ERERGHDyJiIiMOHgSEREZ+RoYsgRhtMVP6+vrxfJUP7zXAi/aQtZ9+/ZNKNOmetMCCtoDb7/aHvap8rygfaZaeU5OTkKZFmYIS9hC2z+06egkYV/Y20oK32j9pYXH/JqiTmMNvEhTEGqhI40U5vST9llbznGlpaXeVMaIV55ERERGHDyJiIiMOHgSEREZcfAkIiIy4uBJRERk5EnaVktpTpkyRSxfsmRJQpmWLNOmtLMu8uoXre1SuTWNmerUn7V+0hRf1kWvLQlQL2ht1BYklxYC1/ZJbUF3a+LRL9qxIdVbWxA67KlajdR2y4LLgL6PaAtId5Z1YXnpvKBNwyelyAHgoYceSqZqntH2J23qT+l41Fj714pXnkREREYcPImIiIw4eBIRERlx8CQiIjLi4ElERGTkSdpWS/FpiT0pRaqlbbW5FrVkY6rTmxop0aWlZ7W2pHouTS35VlxcLJZLi+++9957ptcOy3ywGm0floQ9iartf5WVlQlllmMXsKUmW1paxG0ttMSpNkd2Y2NjQpmWgtYSqqleIFz7TLXzhfSZSHNsA/4lhK2s/VhSUpJQps0v7ve5hVeeRERERhw8iYiIjDo3eFZUACNHotfttyNz3jzg7FmPqhUilZXAqFHAyJFASH7Z3XMffggUFAAjRgBLlwZdG+/NnQsMHOj6MaoOHgSmTAEKC92+KtyK7fLOngVuvRUoKkKv22/HT198Mega+aOtDRg7Fpg+Peia+Cc3Fxg9Gr3uvBM9lcl0wq7jg+fhw8CrrwI1NTj18cfAhQvIePddD6sWAnv2AL/5DbBjB1BbC7z/PrBvX9C18lZbG7BgAbB+PfDZZ8CqVe7PKJkzx31BiLL0dGDZMmDvXmD7duCNN6LXj927A5s3A7W1OLV1K9I3bULaX/4SdK28V1npvgRFXVUVTn30EU5XVQVdkw7p3JVnayvQ3Ay0tiLW1IQLN9zgUbVCYu9e4LbbgMxMd3IqLgaUQEyXtWOHu+LMzwcyMoDHHwcMU2B1CXfdBVx/fdC18NeNNwLjxrn/7tXLnXwPHw62Tl6LxYCePd1/nz/vfmKxYOvktUOHgN//HnjqqaBrQj+i42nbIUOAZ58Fhg1Dnx49gHvvRbdHHrlsEy3RJSXAtHSfNteilvrz1KhRwL/+K3DiBNCjB/DBB8CECUnVQ5pXUUuWaXNmpiSJevgwMHToD3/Pzgb+/OfLNtFSv1LbtfkktYRg2El9oKX7amtrxXKt331L5zY0ALt2AZMmXVaszRcqpUi1fU/bF7S2SOeAc+fOidsmpa0NGD8evfftw6lf/hKNI0YA7T5fKQFupZ1ztM/PUwsXAi+/DJw61YH/dWFCmXZeTUlbriYWA+69F2mnT+PIL36Br37xi8v+WUrVAnISOtW/lXBJx688GxvdFUp9PXDkCHDmDPDWWx5WLQQKC4HFi4GpU4H77weKitwVaJTE44llUfs2fy05fRqYOdM9n+/dO+jaeC8tDdi9G4c+/hgZtbXoVlcXdI288/777tn8+PFB18R/27YBO3fi/730EoasWYMs5YtnmHV88Ny4EcjLAwYMALp1Ax55BPjTnzysWkjMmwfs3Als3epu/f3sZ0HXyFvZ2S5scsmhQ8DgwcHVhzru/Hk3cD7xhDseI+xC7944e9tt6KH8PmCXtG0bsG6dC9M8/rh7vvvkk0HXyh8XzzHn+/bF8TvvRO/PPw+4QnYdHzyHDXPBhKYmd/WyaVM0H3J/843788svgXffBWbPDrY+Xps40YWg6uuBlhZg9WrgwQeDrhVZxePui15hIfDMM0HXxh/Hjn1/izZ29ix6/PGPOD98eLB18tKLL7ovrw0N7ji8++7o3c0D3F3Ki7elf9LcjL41NTiTlxdwpew6fg9y0iRg1iwXUkhPd9Hq+fM9rFpIzJzpnnl26+YSjMqMHV1Wejrw+uvAffe550lz57pfdYiS2bOBLVuA48fdlXZ5uRtoomTbNuDNN4HRo4FLzyt/9Stg2rRAq+Wpr74CSkqAtjbceO4czjzwAJr/8R+DrhVZHT0KzJgBABh/8iSO3nMP/n7rrQFXyq5zD/DKy91PlH30UdA18N+0adE6yV5p1aqga+C/O+6Qn19HyS23uCAUgCMpniov5SZPdj9RlJ/vfvUPwF+UsGRXEIsbDrhYLHYMwAH/quObnHg8PiCZDdnGUGMb22EbQ41tbCeKbTQNnkRERMS5bYmIiMw4eBIRERlx8CQiIjLi4ElERGTEwZOIiMiIgycREZERB08iIiIj0wxD/fv3j+fm5nb6TY8cOZJQ9s2lOWSvMHr0aLE8LS0t6fdraGjA8ePHk1oqxNrGtrY2sfzo0aMJZVobteWcLPXws43SklUA0KNHj4SyEydOiNv26tVLLB/afjm0JOrhVxu1ekv7qva6Whst/GxjU1OT+p5XysjIELfV2jho0KCk6+FnGzUtLS0JZZ9++qnpNbRzkfRZ+dlGaZ8EgK+++iqhbLgy968Xy+F50Ubt/Pn111+L5d99911CmbZfa2NEfn6+WN5bWIXoam00DZ65ubmoqamx/C+i559/PqHslVdeEbetUlYZt3T+hCvW4Lwaaxu1tRql9mhtnD59ulhuWQPTzzZqa/9Jaz5qddbWdtU+E4mfbdTqLe2ry5cvF7fV2mjhZxu1tVal/tVO5lobLevr+tlGjfQFIc84Gfm6devEcumz8rON0j4JAOXCVKnLli0Tt9XWLLXwoo2NjY3i9i+99JJYvmHDhoSynTt3ittqX/R+/etfi+X33HNPQtnV2sjbtkREREYcPImIiIw4eBIRERlx8CQiIjLq3HqeHbRFWMNNCwB5kQrzgiVsAcgBBa0t0ucRJlq9pc9E21YL5GhBEy8SlhZr1qwRyw8cSFxFyRqKCgstaFJ7cW3FHysDgLVr14rlDz/8sFie6n7UaInxMNPCiNq+KoWAtH4Jy2pa+/fvF8s/+eQTsXzq1KlJlQFyuAgAFi9ebHpPDa88iYiIjDh4EhERGXHwJCIiMuLgSUREZMTBk4iIyMjXtK2WUK2urk4oq6io8LMqnSalLgF5ijpAbrslmRsmWmJPmlpPS1d6MX+vnyz9uHLlSnFbLc2a6jZq6W0tKVtWVpZQprVF+5xSTUuiauccrT2S4uJisTzV/agdM1ofSClwy359te39Mn78eLFcS8pKtMTuO++8I5Y//fTTSb/21fDKk4iIyIiDJxERkREHTyIiIiMOnkREREYcPImIiIwCSdtKtERnWGiLx+bk5IjlUrJRm5NSa7uWwk116k9L4EltLCkpEbe1LOwdBG2OXSm5qn3+2mto/R4WlgXJtdR5qmn706JFi1JbkQBo+5mUQNbmKA5Lyt1KStYOHz5c3HbcuHFi+fz58z2pC688iYiIjDh4EhERGXHwJCIiMuLgSUREZORrYEibQkuSl5cnlhcVFYnl5eXlYrkW7PHL2LFjO/0a2nRvWmAo1Ytna4EmqW+0KQjDsqi5xouFyrXPKdVToVkX5ZaOU+3z0Kau0wI8lmnxLLTQjNZ2KRRlPe7CQttvpM9E66+wH4+a/Pz8hDJt7HjuuefE8r59+3pSF155EhERGXHwJCIiMuLgSUREZMTBk4iIyIiDJxERkZGvaVtL0k5akLcj2/uVttWSw0uWLBHLpZSmluLTEqphn7JQaqNW51QnhINQWloqlmvHQaqn7cvKyhLLpfppU/Zpx0FYpnvTkqiW+oWlLRotvS0lnrVEcZRMnTpVLF+8eLFY/uijj3ryvrzyJCIiMuLgSUREZMTBk4iIyIiDJxERkREHTyIiIiNf07ZawtKSItXmsKysrBTLpURrS0tL0u+n0eaC1JKUUoJWSyr6Nf+nlTVJKW0f9nlBNVrbLQu619fXi+XSouGAf/uqRkt1W1K/2ucU9mS4JUFbXV0tlodlcXrLZ71r1y5Tufbafs3DrHnppZfE8sbGxoSyd955R9zWMrd6R/DKk4iIyKhzg+e33wKzZgE33QQUFgIff+xNrcKirg4YM+aHn969AeX337q0igpg5Ej0uv12ZM6bB5w9G3SNvFdZCYwaBYwcGc0+BIAPPwQKCoARI4ClS4OujffmzgUGDnT9GFUHDwJTprjz6ciRbr+NmrNngVtvBYqKXBuV35UPu84NnmVlwP33A59/DtTWug6PkoICYPdu9/PJJ0BmJjBjRtC18tbhw8CrrwI1NTj18cfAhQvIePfdoGvlrT17gN/8Btixw+2n778P7NsXdK281dYGLFgArF8PfPYZsGqV+zNK5sxxXxCiLD0dWLYM2LsX2L4deOON6PVj9+7A5s3uWNy92/Xp9u1B18qs44Pnd98BW7cC8+a5v2dkAF10jbikbNoEDB8O5OQEXRPvtbYCzc1AaytiTU24cMMNQdfIW3v3Arfd5r78pKcDxcXAe+8FXStv7djhrjjz892x+PjjgPKstcu66y7g+uuDroW/brwRGDfO/XevXu6C5PDhYOvktVgM6NnT/ff58+4nFgu2Th3Q8cFz/35gwACgtBQYOxZ46ingzBkPqxYyq1cDs2cHXQvvDRkCPPssMGwYet90E+K9e6P17ruDrpW3Ro1yX/ROnACamoAPPnC3x6Lk8GFg6NAf/p6dHb2T7rWmoQHYtQuYNCnomnivrc09Chs4EJg6tUu2seNp29ZWYOdO4LXXXMPLytxzlhde+H4Ty4rnWuJUS9Vqc9hKybeMjAxx26S1tADr1gEvvpj0/yIlvbRV7gPV2OiuUOrr8ZM+fZDx6KPIeP994Mknv99ES61J7dH6K1CFhcDixe4g7dnTPWtJv3zXl+YFBYBFixYl/TZFRUViubavSgnutLS0pN/vMvF4YtkV3+a15LqUKNaS8trnpKXRw0LaV4uLi8VttYR1StO2p08DM2e65/O9e1/2T1o/Sqlp65zSWvJaep22tjbTa18mLc3dsv32W/cobM+ey55lL1We2UvnonvuuUfcdvny5R2vXxI6fuWZne1+Ln1jmDXLDaZRtH69u5UyaFDQNfHexo1AXp67i9CtG/DII8Cf/hR0rbw3b57bP7dudbf+fvazoGvkrezsy6+mDx0CBg8Orj7UcefPu4HziSfc8RhlffoAkyd3yWfZHR88b7jB3Saqq3N/37QJuPlmj6oVMqtWRfOWLQAMG+Ye1jc1uauXTZuiF/wCgG++cX9++SXw7rvR68+JE10Iqr7e3SlZvRp48MGga0VW8bj7oldYCDzzTNC18cexY+6KE3BZi40b3W9sdDGdmyThtdfct6OWFhdUWLHCo2qFSFMTsGED4PMtgMBMmuTuGowb525ljh0LzJ8fdK28N3Ome+bZrZtLMPbtG3SNvJWeDrz+OnDffe550ty57tcAomT2bGDLFuD4cXelXV7+Q2AxKrZtA958Exg92j0TBIBf/QqYNi3Qannqq6+AkhK3n164ADz2GDB9etC1Muvc4DlmDFBT401Nwioz0510o6y83P1E2UcfBV0D/02bFq2T7JVWrQq6Bv674w75+XWU3HKLC0J1cZxhiIiIyCgWN3zLicVixwAc8K86vsmJx+MDktmQbQw1trEdtjHU2MZ2othG0+BJREREvG1LRERkxsGTiIjIiIMnERGREQdPIiIiIw6eRERERhw8iYiIjDh4EhERGZmm5+vfv3/cl+V3ANRdmmD+Cnl5eWK5ZZmxhoYGHD9+PKnVVq1t1Ordq1evpF9DW4ZqkGEVFz/bqC09JLVd23b48OFieWZmZtL18LONmiNHjiSUnTBO11hQUCCWS/uwn23UltRqbW1NKNP2Pct+fbV6+NXGg8o6radOnUoo69evn7it5bjTBNGPUht79OghbjtYWXEnLMdjS0uLWP7FF18klGnL4WlttLhaG02DZ25uLmp8mstWW+tSWz/Q0hETJkxIeltrG7V6W9bu1DpfW7dP4mcbLet5atu+/fbbYrm25qvEzzZqpHVmtX1Ss27dOrFc2of9bOOcOXPEcqnPtH3PizVp/WyjVm9pPUrt87Acd5og+lFqo3Z8aesnh+V41L4gPPzww0mVAXobLa7WRt62JSIiMuLgSUREZMTBk4iIyKhz63l2kPTMSLvHrT0PTLXdu3eL5dXV1UmXP/TQQ+K2XjxH8tMrr7wiltfW1iaUFRUViduGpR+tpOeSWn+tWbNGLNeeoWnbp5r0rEw7Hi2vAaS+37XjVNpXFy1aJG6rPUPzKyyp0T7TlStXiuXSsae1RSvXPr9U96PWdqkfpTJA7y/tmbEVrzyJiIiMOHgSEREZcfAkIiIy4uBJRERkxMGTiIjIyNe0rZaYKi0tTSirqKgQt9WSnl7MHmGhpc1ycnLEcim1FvbEqZawLC8vT/o1vJgRKkykZJ6W1tPaGJZ+1+onpYe1JLD2GlpKMyxJcimJqqU0tfOWVylNv0h9pvWX1r/a8evFrEsWffv2FcuzsrISyqxtZNqWiIgoIBw8iYiIjDh4EhERGXHwJCIiMuLgSUREZORr2lZLaJWVlSW9bSwmr7Xq97yFV9KSeRrL3LZhoa3FqSkuLk4oC3uqVksUaylDKUWqfU4HDhwQy8PymVjWcNQSwpbEbhC0419K+Gu0zynVaVst9aux7Gda/+bl5Zne0y/auVLqG22OYuv8zFa88iQiIjLi4ElERGTEwZOIiMiIgycREZGRJ4EhLWyhhWykgIK2OKsm1Q/vtUWetfCI1B4pKAXoUxCmmhZ40UgP5LXFwcMSltL2VcsUhFapnp5P2ye1Y8YShtOm4QsLrY1SuRYo0UIzWtul81nYddUpCKVgqRY2tU4lae1HXnkSEREZcfAkIiIy4uBJRERkxMGTiIjIiIMnERGRkSdpWy2hpS1o+t577yWU+T2VUmdpyS0t2Si1R0vxWdNiftEW9tZI6VxranrFihViuV+pP23qNcvi6lobw55g1Oq3a9euhDItlay1Rds+zLTjy5qKD3PbrVNJdsXksEY7r2rHurZ4toZXnkREREYcPImIiIw4eBIRERlx8CQiIjLi4ElERGTk62LY2nymUrmWWLMsYhsELcFoWchWSxqnOm2rvZ+WwrXOhSuxpjpTTUrsrV27Vty2oqJCLE/13Lba+2nl0lyfWr9Y09Spps1bKh2PWrpSOx61/V1Kb7a0tIjbWmgLjGvzMEvJWu04ysrKEstTva9aWRan15LDlsWzr9aPvPIkIiIy4uBJRERk1LnBs60NGDsWmD7do+qEUG4uMHo0MGYMMGFC0LXxx7ffArNmodett6LXpElI27Ej6Bp5q67O9d+ln969gZAsA+epigpg5Ehg1Chg9mzg7Nmga+S9ykrXvpEjo9mHAPDhh0BBASY98QSGvf120LXxRwT6sXODZ2UlUFjoUVVCrKoK2L0bqKkJuib+KCsD7r8fp3bswKmPPsKFgoKga+StggLXf7t3A598AmRmAjNmBF0rbx0+DLz6qttH9+xxX2xXrw66Vt7aswf4zW+AHTuA2lrg/feBffuCrpW32tqABQuA9eux47e/xcBNm5AZ8tnXzCLSjx0fPA8dAn7/e+CppzysDqXcd98BW7cC8+a5v2dkIK6ECSJh0yZg+HDAOBVhl9DaCjQ3uz+bmoDBg4Oukbf27gVuu819+UlPB4qLAWGqzy5txw5gxAggPx/xbt3wzd13o/+2bUHXylsR6ceOp20XLgRefhk4dcqTimjpviVLlnjy+h0WiwH33uv+fPppYP78y/5Zm+9SSoVpc2ZqqbqU2L8fGDAAKC1Fn9paYPx4d0fhuuu+30RLJUpJVC3tqKX4Up7eXL3a3dJMktSeoqIicdtAE8JDhgDPPgsMGwb06OH22XvvvWwTrX5SWlSb/zPQNo4aBfzrvwInTrg2fvBBwqMULeVumbdUS51r6U1p+4yMjKTf7zKHDwNDhwK4eF44eBD485+R3+4cof0WgzSXeHFxsbit5bcBPJdEP2qJZ+lcaZ13XDt+rTp25fn++8DAge5EG3XbtgE7dwLr1wNvvOGu0qKktdW171/+Bdi1yw2aS5cGXSt/tLQA69YBjz4adE2819gIrF0L1NcDR44AZ84Ab70VdK28VVgILF4MTJ0K3H8/UFTkrlyiJB5PLIvFUl8PP0WkHzs2eG7b5k5CubnA448DmzcDTz7pbc3C4tKtr4ED3XOyqIVpsrPdz6RJ7u+zZrnBNIrWrwfGjQMGDQq6Jt7buBHIy3N3Ebp1Ax55BPjTn4KulffmzXP759atwPXXAz/7WdA18lZ2trvavOTQoejdfgci0Y8dGzxffNF1akODuw12993R+5YLuG/vl25LnzkD/OEP7pZDlNxwg7tNVFfn/r5pE3DzzcHWyS+rVplu2XYpw4YB27e7Z53xuOvHKIb5vvnG/fnll8C770avPydOdOGZ+np3p2T1auDBB4Oulfci0I9d71o5lY4e/SGV2doK/PM/u9sMUfPaa8ATT7iDNT8fUNbY7NKamoANG4Dly4OuiT8mTXJ3DcaNc7fAxo5NeD4fCTNnumdl3bq5xyjKmsFdVno68PrrwH33ueTt3Lnu1zmiJgL92PnBc/Jk9xNF+fkuSh11Y8ZE99dwLsnMdAdrlJWXu58o++ijoGvgv2nT3E+URaAfY3HpAbW2cSx2DEDnJzRNvZx4PD4gmQ3ZxlBjG9thG0ONbWwnim00DZ5ERETEuW2JiIjMOHgSEREZcfAkIiIy4uBJRERkxMGTiIjIiIMnERGREQdPIiIiI9MMQ/37949Ly7+0tLSI23/xxRdieXNzs+VtRVnKmpMjRoxIKGtoaMDx48eTWppAa+MJZXaao0ePiuWDhcmcm5qakqnC9wYpE5inpaUllHnRRitpyZ+D7Se1bqdAWWDbsnSTF23U+uCvf/2rWD5w4MCk69e9e3exvF+/fkm/hp/9qO3DR44cSSjr1auXuK20XwOp70fNZ599JpZnZmYmlA29uPTXlaTjy8rPNmrnHInW59o5+Oc//7lYLu0PXrSxra1N3F7aJwHgm0tz4rbTo0cPcVvtuNPOq5KrtdE0eObm5qJGmMZNW3tNW6ux1oMp77Q1MKV1+yZcsVbc1Wht1NYb1dbzLBemSdu1a1fS9QDk9TIBeW1ML9potXbt2oQybc3SdevWqXVJlhdt1NYb1fan+Yb5YbW2WNbA9LMftX1YWrtT+zy0dT5T3Y8abc1NqVw7drW1Zy38bKNWb4nW59o5eLky97O0P3jRRm3NTW0/q6ysTCjTBnztuNPOq5KrtZG3bYmIiIw4eBIRERlx8CQiIjLi4ElERGTkyWLY2sNnrbykpCShbMalRaevoKVqtWCAX7RQlNZGLSxl4UUAxQvaQ/0lS5YklGn94kW61wtaW06ePCmWS8EvTVFRkViuhW9S/ZlYghJasErr3y1btpi27ywprAbox6PU71qYxvI5BUGrt0Rri/Ya1kBdZ2n1kIKfAFBVVdXp1/Cqf3nlSUREZMTBk4iIyIiDJxERkREHTyIiIiMOnkREREaepG0bGxtN20sJvJycnKS3DYI1GSlNU2dNovqVcLOqrq4Wy6Vko5ZwCwvr1GtSP2ppvbAkirVkuJYoltLvWoJR24et01d2lpbC10gJda1uYU/ban0gtVHrF+04SHWSX6uHloqXzi8rV64Ut33ooYc6WKvk8MqTiIjIiIMnERGREQdPIiIiIw6eRERERhw8iYiIjDxJ22rzIWoWLVqU9LYrVqwQy1OdCrOSFm3VEoJaWiwstDS11B5tbtGwJFGtaVupH7UEY6rnd9VY26jNK2157SlTppjes7O0/UlL7VvmKNb6NyznHK3tUh9ISWogPKl47TPVxhQpSV5RUSFu61fS+xJeeRIRERlx8CQiIjLi4ElERGTEwZOIiMjIk8CQ9tBXCxdI085Zp8pK9cN77f20h/fSVGjaw3vtgbff00tdSZsSS+sDSxu1qQat04d1ltZfWh9I9dDqnOop6jTWz04L2Ui0fcQ6RWdnaf2oBU2kci00o/WXtsC9X/uq1hbLYtiWbcPEi2Pm+eefF8u16SutoUZeeRIRERlx8CQiIjLi4ElERGTEwZOIiMiIgycREZGRJ2lbbfoxrVxK7GkpvrDTUqRSUk5bjDgsC35rfaCl0KTttYSgllTUEnGpTqhqiWKpjVqdwzIFodaP2vSQBw4cSCizTrmp9W+qWRL+2rGrHY9aOtev5L/1/aQ+W7t2rbhtqpP8QdD6V5tG09qPvPIkIiIy4uBJRERkxMGTiIjIiIMnERGREQdPIiIiI0/Sthot1SQlG7VFlLXFsFNNSzBqqVApKaelHcO+yK7WRmnxXW0uzbCnqbVUYllZWUKZ1hYthZtqWuJUS3tLx5iWttUSjH7N72ql9eOuXbsSysaOHStuq7VR61+/jl/rfNDS8Su1GwhP2lbbz7TPVEp1a/2ovXZpaWkSNftxvPIkIiIy6tzgmZsLjB4NjBkDTJjgSYVC52Ibe915J3oKV1qR8O23wKxZwE03AYWFwMcfB10j710L++qHHwIFBcCIEcDSpUHXxh+VlcCoUcDIkUCKfxc4ZSoqgJEjMbG0FIUvvICftLQEXSPvXezHgpkzMeD//t+ga9Mhnb9tW1UF9O/vQVVCrKoKp9J9vcMdrLIy4P77gf/4D6ClBWhqCrpG/ojyvtrWBixYAGzYAGRnAxMnAg8+CNx8c9A1886ePcBvfgPs2AFkZLh99oEHgJ/9LOiaeefwYeDVV4HPPsNf/vxn3Pz88xi4eTO+vv/+oGvmnXb9WPfZZxi+YAFO3nEHWgxL44UBb9te6777Dti6FZg3z/09IwMIyfMrMtixw11x5ue7Pnz8cUB5/tdl7d0L3HYbkJkJpKcDxcXAe+8FXSvvtbYCzc2ItbUh7dw5nOvXL+gaeeuKfjw9fjz6VFUFXSuzzg2esRhw773A+PHAv/2bR1UKmYtt7Dl5MjK66MKyV7V/PzBgAFBaCowdCzz1FHDmTNC18l7U99XDh4GhQ3/4e3a2K4uSUaPcF70TJ9zdkQ8+AA4eDLpW3hoyBHj2WWDYMNw+cyZar7sOjRMnBl0rb7Xrx1hzM3r/8Y/o9vXXQdfKrHP3IrdtAwYPxpc1Nbjhl7/EiawsnJs06ft/ltKYgJw6XbJkibht4EnUi23883vvoejZZ1Efi+FkUdH3/1xeXi7+b1IbtfRxoHPbtrYCO3cCr70GTJrkbuEuXQq88ML3m2ipPylRrM1xGnjS+GI/nty3Dz1nzEDTkCFo+2//7ft/LikpEf83KUWqrUQfaOI0Hk8si8Uu+2tFRYX4vy5atCihTEtjpnrO4csUFgKLFwNTpwI9ewJFRe4KtB3tPCLR2qKlkovaHfe+aWx0dwzq69EE4Po5czCxrg7n/+mfvt9ES3uvXLkyoSwsv61wmXb9WNSzJ/AP/4DrevTAgHbnQUvSWJsDWHuN4uJiW30VnbvyHDwYAHChf3803Xcfuiu/btKlXWzj+b59cfzOO9H7888DrpDHsrPdz6UvPbNmucE0ai72Y3zAAJyfPh3pUWtjdvblV2GHDn3f5kiZN8/tn1u3AtdfH63nnQCwcSOQl+fuBnXrhpZf/ALpO3YEXSvvRaAfOz54njkDnDoFAIg1NeGnH32E8wUFXtUrHNq18SfNzehbU4MzeXkBV8pjN9zgbvfV1bm/b9oUrZAJcFk/4swZpG/ejLbCwmDr5LWJE4F9+4D6ehf6Wr3aBYai5ptv3J9ffgm8+y4we3aw9fHasGHA9u3utnQ8jm7V1WiL2nkViEQ/dvy27dGjwIwZAIAbm5tx5sEH0ezR5XBotGvj+JMncfSee/D3W28NuFI+eO014Ikn3Ek3Px8I462ezmjXj71aWtAycyZa77kn4Ep5LD0deP114L77XPJ27lz36xxRM3Ome+bZrRvwxhtA375B18hbkya5uz/jxqFXLIa2W25Bi/JIoUuLQD92fPDMzwcu3qY9ojwD6vLatfEvyvPKSBgzBqipCboW/mnXj6dCPtNRp0yb5n6i7KOPgq6B/8rLgfLyaO+rEehH/qoKERGRUSwupfS0jWOxYwASl50Pv5x4PD4gmQ3ZxlBjG9thG0ONbWwnim00DZ5ERETE27ZERERmHDyJiIiMOHgSEREZcfAkIiIy4uBJRERkxMGTiIjIiIMnERGRkWl6vv79+8dzc3OT3v6LL76Q3zQ98W3PnTsnbjtYWRmiV69eSdejoaEBx48fj/34lvY2ag4K6wyeOHFC3Hb06NFieVpaWtLvF0QbJXWXJpi/wqBBg8RyyzJeYe/HHj16iOUFhom9/Wyj1BYA+ObSJN2dMHz4cLFcW9ItDG3U+kvbV/sZFqX2oo1tbW3i9p9++qlYLvWB5TxpFcTxKH0m9fX14rbdu3cXy4e2X/f2R1ytjabBMzc3FzWGOVC1tR0tayQ+//zzYrm2VptkwoQJSW9rbaNm4cKFCWXSWnQAUKWsom4ZWIJoo0TrF2nNSEBfN1IS9n7U1mXV1nGV+NlGqS0AUFlZmfRraJYtWyaWS/0bljb+/Oc/N72GZe1ZL9qordupDULLly9PKLOcJ62COB6lz0TrF+1zsqxJe7U28rYtERGREQdPIiIiIw6eRERERh1fzzMJ2j176fmmdm9+ypQpYnljY6NYbnlO6AXteZb0jKVYWSw81XX2itSP1dXVptewPPP0k9aP0nMT7Tm85VmKn7Tjbs2aNWJ5ibDYsva8qLy8XCzftWuXWJ7q/tWeO0tt1zIZpaWlYrnlmacXtH48efKkWK6dKyU5OTliueU4CIKUN1i7dq24bVFRka914ZUnERGREQdPIiIiIw6eRERERhw8iYiIjDh4EhERGfmattXSbFJiSpthSBOWhKrWRinNps1Mo72GlurUEoV+0VJ/lvRhWPpLo6W9LTO0aP27e/dusdyvftQ+a8sxZk0Oa/twqmn7pHQsZWVliduuXLnSwxp1nGVmKkBONlv3Me1YTzWt7Zb90s/ZlQBeeRIREZlx8CQiIjLi4ElERGTEwZOIiMiIgycREZGRr2lbLfkmre2opby0tS5TTUt/afNMSm3X0o7a3IxaalJLdXaWVj+tHy3z2IYlbav1ozbvq2XtWU2q5wXV0r1aG6XtrUlPLRmuvWeqjR07NqFM2ye1eV9TrW/fvp1+DandQHjmlNbOLVriWar3gQMHxG39PufwypOIiMiIgycREZERB08iIiIjDp5ERERGvgaGFi5cmPS22sNdv6dYSpY1+CCFSiyfB6CHMPyihUS0vpE+E2lhZSA8/aiRFi8H5CnctJCYRtt3/FpcWXs/bSFriTZ1nRY0SfW+aiXVWwsjavuqFsTyKxCmfdZauVS/srIycdvi4mKxPNXBPi38aJnqUgtc+h3U45UnERGREQdPIiIiIw6eRERERhw8iYiIjDh4EhERGfmattXSmxUVFQllWkJQW/zUmlztLOviwFp6U6JNB5bqad209KdWLk2pqCVRtaRiqmlJyng8nvRraP2i7cOpXrxcS75q/ZiXl5f0a6T6uPOTdkxbp6m0TmXYWdp+JqVOtUXKtTRrlPrXOo2mFa88iYiIjDh4EhERGXHwJCIiMuLgSUREZMTBk4iIyMiTtK01bSalD7UEWdhTYVpiT5ojUptbNOzzgmq0Bcwlfiff/CLtZ1raNtWpWivLIup+zbvrN+1cJJVrCXDtNcLSv1o/lpaWJv0aYWmLlbbwtYRpWyIiopDh4ElERGTUucGzogIYORITS0tR+MIL+ElLi0fVCpG2NmDsWGD69KBr4o+5c4GBA4FRo4KuiX/q6oAxY3746d0bME56EXrXQhvPngVuvRUoKgJGjgSWLAm6Rv7IzQVGj3b9OGFC0LXxXkTOOR0fPA8fBl59FaipwV9WrECsrQ0DN2/2sGohUVkJFBYGXQv/zJkDfPhh0LXwV0EBsHu3+/nkEyAzE5gxI+haeetaaGP37sDmzUBtrWvnhx8C27cHXSt/VFW5NtbUBF0T70XknNO5K8/WVqC5GbG2NqSdO4dz/fp5VK2QOHQI+P3vgaeeCrom/rnrLuD664OuReps2gQMHw4oUyJGQlTbGIsBPXu6/z5/3v3EYsHWiewics7peNp2yBDg2WeBYcNw509/itYpU5Dz3/872h+uWqJLSvJpCUbrnLKeWrgQePll4NQp8/9qSaJq862GnaWNoUn3rV4NzJ6d9OZSYk+bLzQ0lDZqifaSkpKEMiktHgptbcD48cAXXwALFgCTJl32z9r5QkrWauccLcmfslR8LAbce6/78+mngfnzk6qHNEe2lsztquecoqKihDJtbnC/29jxK8/GRmDtWqC+Ht/t3YtYUxO6/fu/e1i1gL3/vrsvP3580DUhr7S0AOvWAY8+GnRN/BP1NqaluduZhw4BO3YAe/YEXSPvbdsG7NwJrF8PvPEGsHVr0DUiQccHz40bgbw8YMAAoFs3tPziF0jfscPDqgVs2zZ3EsrNBR5/3D1refLJoGtFnbF+PTBuHDBoUNA18c+10EYA6NMHmDw5Es/OEgwe7P4cONA9t47SeTVCOj54DhvmHtY3NQHxOLpVV6OtoMDDqgXsxRfdt9uGBncb7O67gbfeCrpW1BmrVplu2XZJUW7jsWPApUcFzc3uC/xNNwVaJc+dOfPDY6IzZ4A//KHLp1KjquOD56RJwKxZwLhx6PUP/wBcuIAW4dkJhdzs2cDtt7tfdcjOBv73/w66Rv5oagI2bAAeeSTomvgn6m386itgyhTglluAiROBqVOj9ytkR48Cd9zhfh3n1luBBx4A7r8/6Fp5KyLnnM5Nz1deDpSX45QhONIlTZ7sfqJo1aqga5AamZnAiRNB18JfUW/jLbcAu3YFXQt/5ee7X8WJsoicc2LxeDz5jWOxYwCSn1wwPHLi8fiAZDZkG0ONbWyHbQw1trGdKLbRNHgSERER57YlIiIy4+BJRERkxMGTiIjIiIMnERGREQdPIiIiIw6eRERERhw8iYiIjDh4EhERGZmm5+vfv39cWwNP0tLSIpZ/9tlnCWUZGRnittr7ZWZmJl2PhoYGHD9+PKlVc61tbGtrE8s//fTThDKtjQXKhPppaWlJ18PPNmqk9TwPHjwobqu1PS8vL+ntg2hjU1NTQtlf//pXcVttDcyhQ4eK5VL/+tlGqS2A3GenT59O+nUB/Tjt169fQpmfbTylrL0rlX/11VfitsOHDxfLLWucBrGvSuci6Vx7NVrbpfOtn23Uxo66urqEMu0crL2fV/1oGjxzc3NRU1NjemOJtDCy1lBtMVfL4soTJkxIeltrG7UFoaX2aG2sqqoSyy2d7GcbNWvXrk0oKysrU99TovWvtH0QbZQWUdYW2Z2uTFKuLdAs9a+fbZTaAsiLP1dXVyf9ugCwZMkSsVxa+N7PNm7ZsiXp8vLycnHbZcuWieUPPfRQ0vUIYl+VzkXWRejffvttsVx6HT/bqI0d0rGnnYP97kfetiUiIjLi4ElERGTEwZOIiMioc+t5/ojnn38+6W21Z2La8yXtPneqac/sTp48mVCm1Vl7Jmb5/PxkqZ/0/AzQPyft2YYXAQovSG18+OGHxW1XrlwplkvP/QB93/aL5dlrRUWFuO2iRYvE8jVr1ojlWtv9otWjsrIyoUx7TrtixQqx3PKsLAjSsac989SOO+3zsz477Szt3HfgQPKrmpWUlIjlWtstGROAV55ERERmHDyJiIiMOHgSEREZcfAkIiIy4uBJRERk5EnaVpu5REsfSmk2LZWX6rSeRkt/aTOaSDPtaElULb2ptT3VSVQthSb1u5YoDkuKz0pqj5Yc1tqopftSTau3RKuzJbEbhClTpojlUj9qx7Q1oRqWZLhUb+2cE5bjzjp2aAlay2to72lNv/PKk4iIyIiDJxERkREHTyIiIiMOnkREREYcPImIiIw8Sdta55m1pA+1tJiWlPNrPlgtTail1qR6aK+htVFL8qY6gay9n9TvWnI47ClNjVRvLa2nSXUaU1pnFdDnbJX2Ye2Y1uYW1fbhVNPmn5XmsdWOr7Cko62kPtCOO62Nqe5Hy1y1gC0x7nf/8sqTiIjIiIMnERGREQdPIiIiIw6eRERERp4EhrQHszk5OWK5FiqRhGXR67y8PLHci4VVtdCR5eG4n7Q+kIJE2hRXqV742StSOEgLVWjhjFS3vaqqSizXgkRauYW2r2qfSapJfaBN5actkp3q4Jd2XrWUa+E2bSrJsAf4pP3MOo2pV2MKrzyJiIiMOHgSEREZcfAkIiIy4uBJRERkxMGTiIjIyJO0rXVKNktqTUt/pToVpk37pS3OKiUytXZryTfrNHCdpU1tWF5eLpYXFRUllGltCQstqajtwydPnkwokxY6B8K/cLvWRqnPKisrxW21Kf7C3nYppan9NsDYsWM9rFHHaUl+7XiUaP0VlvR7cXGxWJ6VlSWWS2OKNVXr1djBK08iIiIjDp5ERERGHDyJiIiMOHgSEREZcfAkIiIy8iRtq83NqqWapGSelgTU0nNaGjDVtJSh9JloqbDa2lqxXEvK+UVLGWqpRKnefiavvaClDC19Y51z2LKPeEE77rS2S32j9XlYUrUaLYkqJYq11LSW9Ew17bPW+lHaXttXtf3dWt5Z1n1VmodZm6NY60ev9mFeeRIRERl1bvD88EOgoAAYMQJYutSjKoVM1Nt48CAwZQpQWIgp/+N/IP8//zPoGnmvXRsxciQQkrsWnqqrA8aM+eGnd28gJCuaeKqiwvXhqFHA7NnA2bNB18hb18K+CkTivNrxwbOtDViwAFi/HvjsM2DVKvdnlFwLbUxPB5YtA/buxUcvv4y89evR6+DBoGvlrXZtxPbtwBtvRK8fCwqA3bvdzyefAJmZwIwZQdfKW4cPA6++CtTUAHv2uONz9eqga+Wta2Ffjch5teOD544d7ltDfj6QkQE8/jjgwbqAoXIttPHGG4Fx4wAArT164FR2Nn564kTAlfJYuzaiVy/3rf7w4WDr5KdNm4DhwwHluWWX1toKNDe7P5uagMGDg66Rt66FfTUi59WOD56HDwNDh/7w9+zs6HXytdDGdnocPYqs/fvR+POfB10V/zQ0ALt2AZMmBV0T/6xe7W5pRs2QIcCzzwLDhrlBJisLuPfeoGvln6juqxE5r3Y8bRuPJ5bFYpf9VUt6SQlaaS5YQE9panPNeiqJNmr1k+ZQ1eZa1FauT2my8fRp3Lt8ObB8OR545JHL/kn7rKX+1fpcS+Fq2/uSRD19Gpg50z0L7N37sn/S5hGW+lGbv1cr15KKvrSxpQVYtw548cWEf9Lm9ZUSjKGco7ix0V2h1NcDffoAjz4KvPUW8OST32+iJdSl/U+bV9WvFLTJVfZVyxzZWmpVS6ha9+EO6cR5VaLNAWx5jY7o+JVndrZ7uH3JoUPRu4VyLbQRAM6fdwfqE08AVwyckXEttBFwz5HGjQMGDQq6Jt7buBHIywMGDAC6dXP9+Kc/BV0r70V9X43IebXjg+fEicC+fe5bYEuLu1X04IMeVi0EroU2xuPAvHnu2cozzwRdG39cC228ZNWqaN6yBdzt2u3b3bPOeNw92y0sDLpW3roW9tWInFc7PnimpwOvvw7cd5/r6Mcec9HqKLkW2rhtG/Dmm8DmzT/8msMHHwRdK29dC20E3KCyYUM0r1YA9+xv1ix3ZT16NHDhAjB/ftC18ta1sK9G5LzauRmGpk1zP1EW9TbecYf8DCJKroU2Au7XU6KWlL5Sebn7iaprZV+NwHmVMwwREREZxeKGbzmxWOwYgAP+Vcc3OfF4fEAyG7KNocY2tsM2hhrb2E4U22gaPImIiIi3bYmIiMw4eBIRERlx8CQiIjLi4ElERGTEwZOIiMiIgycREZERB08iIiIj0/R8/fv3j3u6NE07dXV1YnlbW5tYXlBQIJanpaUllDU0NOD48eMxYfMEXrVRqveRI0fEbc+dOyeWjxgxIun3C6KN0lJATU1N4raW/rra+3W2jdr+dLD9Kg/tSMvI9ezZU9w2Ly9PLE91G6/22hKpjVqdtffr1auXqR5+tfGEMj3h0aNHE8qam5vFbbX369evX9L18LONn376qVje0tKSUJaRkSFuO1hZxSTVbdTOF3v37k26HlobBw4cqNVFLLeOHabBMzc3FzU1NZb/JWnaunPaGphVVVVieZ8+fRLKJkyYkHQ9vGqjVG9pHVNAP6lZ1lQMoo3SeqPaupiW/tJ40UZtf9LWk7WskaitTZrqNmq09WGlNmp1Xr58uViufSYSP9uo9YG0tmNtba24rRfr6/rZRm2gPXAgcQKfG2+8Udw2LG3Uzhdjx45N+rW1NmrHtNZG69jB27ZERERGHDyJiIiMOHgSEREZdW49zw6Snv1VV1eL22ZlZYnl2rMry/MlP0nPgLRnLGGhfabaMwJpe8vzhCBoz5e150jScxPtOc3DDz8slm/ZsuVH65UKWt9I+6r0jBAApkyZIpbX19eL5X4FDLU+KC0tFctzcnISyrRzi/YaWv+met/WnuVJn8nKlSvFbbU2jhkzxlTeWdr+UVZWlvRraM+5Fy1aJJZrbbE8twd45UlERGTGwZOIiMiIgycREZERB08iIiIjDp5ERERGvqZttXSflgCTaMkov1J8XpESeBUVFeK2WrIx1bS07dq1a8Xy4uLihDItCRgW1jSh1HYt3ad9fmFJhmtpQimlqSXDtRRkqo9Hrb+0WbkeeuihhDJtxq/y8nKxPCz9qB1j0r5qOdcCqe9H7bPTzolS+cmTJ8VtpfMT4F1ymFeeRERERhw8iYiIjDh4EhERGXHwJCIiMuLgSUREZORJ2labu9Oa9JJoCbewkz4Ty/ypQdDmfdWEZb5aP61YsSKhTNsntflWw/45WRKWfs1x6hUpVeuVsJ+LioqKkt5WW88z7Puq5Rzlxfq6V8MrTyIiIiMOnkREREYcPImIiIw4eBIRERn5Oj2fNh2dFDrQFtkNS5hGo01dJ7U97IEhKykUpU15pk0NZ12ANtWkvgnL4tZekQIUJSUl4rZaCEObitMvWjhL25+0KdwstLaHZXpN6fyiTVGnTWOonYvCEiSS9jOtX6xttOKVJxERkREHTyIiIiMOnkREREYcPImIiIw4eBIRERl5kra1Jikt01xZp4zzi5aoW7RoUdKvIU311pVJCUYt4aYtMKx9JqlOb2qkfVibok5LGmtpwDDT9ve+ffuK5VoC2a809YEDB8RyLdEunXO019Cm+AvLPmmh7ZPabzdo+2pYfiNAOva0ftHazrQtERFRQDh4EhERGXHwJCIiMuLgSUREZMTBk4iIyMjXuW2jREtYlpWVieVS+rC0tFTc1joHo18JRu11tTmKpaSxlnzTUnxaIi4sc6VKKU0t0akt/q4lV/2aL1RLs1uSl42Njab3tM4121laIlYrl+qhfU5+L6LcWdp82lVVVQll2rklLLQ+sCRiteNOo+2r1oXeeeVJRERkxMGTiIjIqOOD59y5wMCBwKhRHlYnZA4eBKZMAQoLMXHOHAz5j/8Iukb++PZbYNYs4KabgMJC4OOPg66Rt86eBW69FSgqAkaOBJYsCbpG3mvXxl63346fvvhi0DXyXl0dMGbMDz+9ewMhWQ7MM9xXu4yOD55z5gAffuhdTcIoPR1YtgzYuxc7f/1rDFm7FpkhmfHIU2VlwP33A59/DtTWugE0Srp3BzZvdm3bvdvtt9u3B10rb7Vr46mtW5G+aRPS/vKXoGvlrYIC13+7dwOffAJkZgIzZgRdK29xX+0yOj543nUXcP31HlYlhG68ERg3DgDQlpmJpmHD0P348YAr5bHvvgO2bgXmzXN/z8gAQhKM8EwsBvTs6f77/Hn3E4sFWyevXQttbG/TJmD4cCAnJ+iaeOta6MeItDGQtK2UWtNWPNfmzEy1ybm5wMGD6D9/vrtddKnckCbUEmRaG1OS7tu/HxgwACgtdd92x48HKiuB6677fhNL8k1LdGqsSbkOa2tzbfviC2DBAmDSpMv+WUv31tbWJpRlZWWJ25aUlIjlKUtpXmxjn4tt7HXPPZf9s5a8lNKHWiJRS7M+/PDDhop6YPVqYPbshGLtWKqurk4o01Lkgadqf2RfXaLcypX2VY22r6Ys5X6xjb337cOpX/4SjSNGuMdHF2n7n9RGbezQ5h23pmo1DAwl4/RpYOZM93yl3cAZCa2twM6dwL/8C7Brlxs0ly4NulbeS0tzt8EOHQJ27AD27Am6Rt67FtoIAC0twLp1wKOPBl0Tf1wL/XixjYc+/hgZtbXoVlcXdI3MOHj+mPPn3cD5xBPAI48EXRvvZWe7n0vfbmfNcoNpVPXpA0yeHO3n9VFv4/r17nHKoEFB18RfUe9HABd698bZ225DD+HOQNhx8LyaeNw9CywsBJ55Juja+OOGG4ChQ12SEXDPkm6+Odg6ee3YsR9uCTU3Axs3umRxlFwLbbxk1Srxlm0kXAv92K6NsbNn0eOPf8T54cODrVMHdPyZ5+zZwJYtwPHj7sqlvPyH0ElUbNsGvPkmMHq0i8YDwK9+BUybFmi1PPfaa+7KuqUFyM8HIrbuKL76Cigpcc9ZLlwAHnsMmD496Fp561poIwA0NQEbNgDLlwddE39cC/3Yro03njuHMw88gOZ//Mega2XW8cFz1SoPqxFSd9zhrj6jbswYoKYm6Fr455Zb3PPcKLsW2gi4X085cSLoWvjnWujHdm080oV/9S8WNwwOsVjsGAB5+fVwy4nH4wOS2ZBtDDW2sR22MdTYxnai2EbT4ElEREQMDBEREZlx8CQiIjLi4ElERGTEwZOIiMiIgycREZERB08iIiIjDp5ERERGHDyJiIiMOHgSEREZ/X8oIG0Kax/wuwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 576x576 with 64 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#参考：显示数据集对应的数字\n",
    "\n",
    "fig, ax=plt.subplots(8, 8, figsize=(8, 8)) # 构建一个 8*8 的子图矩阵\n",
    "\n",
    "for i, axi in enumerate(ax.ravel()): # 循环每一个子图位置，并在该位置上显示一张数字图像\n",
    "    axi.imshow(digits.images[i], cmap='binary') # 显示数字图像\n",
    "    axi.set(xticks=[], yticks=[])\n",
    "    \n",
    "    # 把图像所代表的数字显示在图像的左下角，即坐标为(0.05, 0.05)的位置\n",
    "    # transform=axi.transAxes把控制显示位置的坐标系变为左下角(0,0)右上角(1,1)的模式\n",
    "    # - 如果不指定transform参数，则坐标体系与图像本身一致\n",
    "    axi.text(0.05, 0.05, str(digits.target[i]), transform=axi.transAxes, color='red')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "f60a574a-8c0f-4c12-b686-04b5c4763410",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "计算最优K值: 100%:  ▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋\n",
      "当K=3的时候此KNN模型准确率最高，为:0.9944444444444445, 用时:0.97s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1152x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import sys,time\n",
    "from sklearn.datasets import load_digits\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.model_selection import train_test_split\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "#定义显示进度条的函数\n",
    "def progress_bar(Index,Value,times):\n",
    "    for i in range(0, 101):\n",
    "        '''持续调用此函数，并传入i，就可以显示基于i的进度的进度条'''\n",
    "        print(\"\\r\", end=\"\")  # 输出位置回到行首\n",
    "\n",
    "        # 显示进度百分比，并同时显示进度1/2(可以自己调节)个数的进度条符号：▋\n",
    "        print(\"计算最优K值: {}%: \".format(i), \"▋\" * (i // 2), end=\"\")\n",
    "    \n",
    "        # 有的时候大循环中printout不会马上运行，而是等代码运行结束后再依次运行\n",
    "        # 这样有可能让我们的进度条显示异常，所以\n",
    "        # 用flush强制输出,确保以上print语句运行\n",
    "        sys.stdout.flush()  \n",
    "    \n",
    "        time.sleep(0.05) # 程序暂停0.05秒\n",
    "    print()\n",
    "    print(f'当K={Index}的时候此KNN模型准确率最高，为:{Value}, 用时:{times}s')\n",
    "    \n",
    "# 1. 获取X和y\n",
    "df = load_digits(as_frame=True).frame\n",
    "X = df.drop('target',axis=1)\n",
    "y = df['target']\n",
    "\n",
    "# 2. train_test_split\n",
    "X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.30)\n",
    "\n",
    "PredictList = [] #预测率\n",
    "\n",
    "# 3. 创建KNN模型\n",
    "K = np.arange(1,int(np.sqrt(X_train.shape[0])))\n",
    "\n",
    "#开始计时\n",
    "start = time.time()\n",
    "\n",
    "for i in K:\n",
    "    knn = KNeighborsClassifier(n_neighbors=i)\n",
    "    knn.fit(X_train,y_train)\n",
    "\n",
    "# 4. 获得算法的准确率\n",
    "    acc=knn.score(X_test,y_test) \n",
    "    #print(\"当K=\",K,\"的时候此knn模型的准确率为\",acc)\n",
    "    PredictList.append(acc)\n",
    "\n",
    "PredictList = np.array(PredictList)\n",
    "\n",
    "# 制作一个3的图像\n",
    "d = np.array(\n",
    "    [[0,0,255,255,255,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,255,255,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,  0,  0,  0,255,0,0],\n",
    "    [0,0,255,255,255,255,0,0]]\n",
    ")\n",
    "d =d.reshape(1,64)\n",
    "\n",
    "#联合K和PredictList\n",
    "link = pd.Series(PredictList,index = K)\n",
    "\n",
    "#尋找最大值及其坐标\n",
    "def MAX(link):\n",
    "    for IndexValues in link.index.values:\n",
    "        if link[IndexValues] == link.max():\n",
    "            return IndexValues,link.max()\n",
    "index,value = MAX(link)\n",
    "\n",
    "k = index\n",
    "\n",
    "#计时结束\n",
    "end = time.time()\n",
    "#所用时间\n",
    "times = end - start\n",
    "\n",
    "#结果\n",
    "progress_bar(index,value,round(times,2))\n",
    "\n",
    "knn = KNeighborsClassifier(n_neighbors=k.max())\n",
    "knn.fit(X_train,y_train)\n",
    "\n",
    "# 预测点与所有点的距离\n",
    "[distance, index] = knn.kneighbors(d)\n",
    "\n",
    "#绘图\n",
    "fg, ax=plt.subplots(1,k.max()+1,figsize=(16,4))\n",
    "ax[0].imshow(d.reshape(8,8),cmap='gray')\n",
    "ax[0].set_title('[3]',fontsize = 18 )\n",
    "\n",
    "#图像转换为8*8格式\n",
    "b = np.array(X_train).reshape(X_train.shape[0],8,8)\n",
    "#为方便找出对应标签\n",
    "c = np.array(y_train)\n",
    "\n",
    "for i in range(k):\n",
    "    ax[i+1].imshow(b[index[0][i]],cmap='gray')\n",
    "    ax[i+1].set_title(c[index[0][i]],fontsize = 18 )  #标题加上数字\n",
    "    ax[i+1].set(xticks=[], yticks=[])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a443f63-1ac2-4186-837a-6b429137dea7",
   "metadata": {},
   "source": [
    "#### 参考答案"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "44ac270b-4d18-448d-82e6-7f3744f6974d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "计算最优K值: 100%:  ▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋▋\n",
      "当K= 10 的时候此knn模型的准确率最高，为: 0.9888888888888889 用时: 3.21秒\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/lib/python3.9/site-packages/sklearn/base.py:445: UserWarning: X does not have valid feature names, but KNeighborsClassifier was fitted with feature names\n",
      "  warnings.warn(\n",
      "/opt/conda/lib/python3.9/site-packages/sklearn/base.py:445: UserWarning: X does not have valid feature names, but KNeighborsClassifier was fitted with feature names\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxAAAABvCAYAAAB8ZSZ0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAQkElEQVR4nO3dcYwc51nH8d9TG9SStnZEmkSk0dlARUUrnd2koVKQ7AgShVbIIRJSW1ElQWoKUsA26h8UBD5XKgRBZR8KCKwqFwOKogjkuLRpmoDsyx9Vpdi1r02ikKaOLzEWSt3ap9AEEoeHP3Zdnb2zz/N6d2dn1vf9SKfz7nvvzLvPvDM7r2fmec3dBQAAAAAl3tZ0AwAAAABMDgYQAAAAAIoxgAAAAABQjAEEAAAAgGIMIAAAAAAUYwABAAAAoBgDCAAAAADFWjuAMLPNZubLfp4bcnn3XbC8mRE1tVWs47fN7Jtm9qqZvWZmR8zs981sVdPta4qZ/YWZ/buZvWxmr5vZD7tx2WFmP910+5pCXHoRk2rEpRpxqUZcqhGXXpy3VGt7X7G2TiRnZpslHZA0L+mgpFPufl+37FpJn5N0naQpSZdL+oGk70m6X9I/ufubFyzvo5JukLRO0h2Sdrr7TO0fZMzM7B8kfUrSK5L+VdKPJP2qpF+U9C+SftPbutFrZGZvSPqWpGfVic1lkj4i6XpJJyV9xN1fbq6FzSAuvYhJNeJSjbhUIy7ViEsvzluqtb6vuHsrfyRtluSSZvqULUl6XNLfSfozSX8v6aVunQOSVl/scif9R9Jt3c92TNIVy97/CUn7umV3Nt3OhmLz9j7vf6Ebl79tuo3EpR0/xIS4EBfiQlzGFg/OWya0r7T2FqbENyRd7u63uPvvuPsfuftnJP2cOlcrNku6vcH2NeXcZ/6iu58696Z3rsb8Sffl7429VS3g7v/Tp+jh7u/3jastbUJcehGTasSlGnGpRlyqEZcenLf00fa+MpEDCHd/w93/r+L9NyU90n250nZCSbq6+/tYRdm59z5kZmvH05yJ8Ovd399utBXtQ1x6EZNqxKUacalGXKqt1Lhw3nLxWtFXVje58lHrPmzz0e7LlbYTStK50fv6irKfXfbv90v6Zv3NaR8z+6ykd0pao859hL+sTl+5t8l2NY249CIm1YhLNeJSjbhUIy4/xnlLoq19ZaIHEGZ2haR7JJmk90i6WdLPS3pQ0lcabFpTviLpE5L+wMwecvcfSpKZrZa0c9nfXd5E41ris5KuWvb6MXXur/x+Q+1pC+LSi5hUIy7ViEs14lKNuHRw3pJrZV+ZyFuYlrlC0g5Jfyrpd9V5BuKv1AnsintiX9JDkr6mThyeNbM9ZrZb0lF1rsx8t/t3bzXSuhZw96vd3dS5bHq7Ov/DccTMPtRsy5pFXHoRk2rEpRpxqUZcqhGXH+O8JdHWvjIJaVzTdKvdW5eukfQbkj6vTsqrj50byQ663EnUHbVvVScl2i9IelOdh87/WNJ96qQA2+juR5tqY5uY2ZSk5yV9190/2HR72oK49CIm1YhLNeJSjbhUW8lx4bzl4rSlr0z6FQhJkru/5e4vufuspM+o09k+33CzGuHuZ939i+6+wd3f4e7vdvdb1RlUbZD0uqRnGm1ki7j7ojqx+UD3ljiIuFQhJtWISzXiUo24VFvJceG85eK0pa9cEgOIC3yt+3tzk41ooU9Jerukh/2CSfagn+n+XrGXSPsgLr2ISTXiUo24VCMu1YjL+Thv6a/xvnIpDiCu6f4+22grGmJm765478PqPK3/31qBV2bM7P1mdnXF+28zsy9IulLSN9z99Phb1xzi0ouYVCMu1YhLNeJSjbhU47yl1yT0lYnMwmRmvyTpO+7+2gXvv1PSbPflV8fesHZ4wsxel/S0pFclfUCdB5H+V9Lt7l6Va/lSd6ukvzSzJyV9T9IP1MlosEmdh5H+S9Knm2teY4hLL2JSjbhUIy7ViEs14lKN85Zere8rEzmAkPQ5SZvNbF7SS5Jek3StpF+TtFadh2/+vLHWNeufJX1c0m9Jeoekk5K+JOledz/eYLua9G+S9ki6UdK0On3kR+o8hPSPkv666oH7FYC49CIm1YhLNeJSjbhUIy7VOG/p1fq+MpFZmMzsY5I+KenD6ozIfkrSaXUm1nhY0v3uXnkL06WehQkAAACo00RegXD3r2rl3qIEAAAANGYSHqLeYWZuZs8NsxAzu8/MXJ2rDwAAAAAG0OYrEMd1/jTmp4Zc3qMXLOPgkMsDAAAAVpzWPgMBAAAAoH0m4RYmAAAAAC1RdAuTmd2qzvwKqyR9yd3vTf5+4Msa11133aBVh3L48OGB67q7ZX8zTEwOHjzYt2zTpk1h3aWlpb5l27ZtC+s+8MADYXmkJCZSHJd169aFdR955JG+ZdPT0yWrrxTFTJJuu+22vmXRtpJGE5fNmzeHdaPtNjU1VbL6SllcNmzY0Lfs+PHjYd1RxGXt2rVh3WjbDNNf5ufnw/Kov5w5cyasO4q4ZHbv3t23bOvWrYMutvH9qKljbmRhYSEsj/btcfSVbB+KjrnDxGV2djYsz76rIqOIy5133hnWnZubu7hGLRPtJzMzM2HdaN/NjOPYMsx+tLi42LcsOzfJ4hYZR1yi9u3YsWPQxaY2btzYt+zo0aNh3aq4pAMIM1sl6W8k3SzphKSnzOzL7v5sVncQhw4dqmOxKbOiPgMAAACsaCW3MN0g6QV3P+bub0h6SNKWepsFAAAAoI1KBhDXSHp52esT3ffOY2Z3m9khM2vmEgIAAACA2pU8A1F1b0/PvV/uvkedabeHujcMAAAAQHuVXIE4IenaZa/fK+lkPc0BAAAA0GbpPBBmtlrS85J+RdJ/SnpK0ifd/ZmgTuuuQBR8zmGWXWtGkCj7RvbkfJQ1I8tUEGVBGkdGkCzzxjBZXCJZFoQo606WIWkUcck+W7RtsphG2/zAgXgS92h77N+/P6w7jrhEWaKyuERZWLJsIqPOfFEliku2n0f9PcuOE2XXymIaffaoL0nDH3Oz/TQ6bmYZYKJ+lvWV9evX9y0bRyaz6HNLcdyyuETt37VrV1i36X0oywgYZUPKMlsNk72q6WNuto9H23Xv3r1h3aivZdkE6z6f665j4HO66Psk62uRbHtE+3eWaWygLEzuftbM7pH0dXXSuN4fDR4AAAAAXLqK5oFw90clPVpzWwAAAAC0HDNRAwAAACjGAAIAAABAMQYQAAAAAIoxgAAAAABQjAEEAAAAgGJFWZhQryxPdCTKOS7FeX/XrFkz8LKHmWehVJRbu6Q8kuXGj2S50uuW5WuO8q1nfS3KIx3NfyHlecfrln22aLtl8wJEudqzuRKyPPV1O3LkSFge5ZLPtnl0HMi2R9aP6zTMnCHZfAxRP1taWgrrZsuuW5aDPtpPsrZHx+u2xyVbfzZvyaDLzvahhYWFgdc7CsMc24Y578lE/XQc5y6ZbM6USPQdnZ3T7du3b+D1VuEKBAAAAIBiDCAAAAAAFGMAAQAAAKAYAwgAAAAAxRhAAAAAACjGAAIAAABAsYlK4+ruTTehEVGqtCi9pCTt2rWrb9ni4uLA6510UQrJvXv3hnWHSR87CsOkNMzqRmngNm7cOPB6xyFLabxly5a+ZVlq3ijNZNNpfTPDpNfN0g1OT0/3Ldu+fXtY98yZMwO0aDyi/SRLAxkdk2+66aYBWzQe2T4UyfaDaP/buXNnWLfNfSWTpSudmprqW5btu02nt832hSi9bZb+OopLpu1pXKM+kZ1f3HHHHX3LspiOOtU6VyAAAAAAFGMAAQAAAKAYAwgAAAAAxRhAAAAAACjGAAIAAABAMQYQAAAAAIoxgAAAAABQzOqYW8HMWjdhQ/Y5zWyYZaeV64pJlO9Yiuc7yHJ+D5MTvCQmUnN9JcoFnX3uKObZ3BlNxyXrL1Eu9yzPe9TXMk3HZd26dWH5zMxM37IsplF/yvLbNx2XLId9NE9ElPdfiudEyHK1N3nMjfqCJO3YsaNv2cLCQlg36ktt7yvZ9o7m14nmn5Hi+QSy3PZNxyUzzFwO2XEr0va4RLLzuWhekWz/bTou2X4e7Svz8/Nh3ey7KlIVF65AAAAAACjGAAIAAABAMQYQAAAAAIoxgAAAAABQjAEEAAAAgGIMIAAAAAAUI41r16Smcc1EaRiz9HGTnK40E6W/e/HFF8O6UdrAKN2g1P64RP0l2+ZR6s0sxeskx+X06dNh3e3bt/ct2717d1i37XGJZMeXKAXsKFItNhWTqK/Pzc2Fde+6666+ZVG8pMnuK9lni1IhZ2m32x6XKP1tljp7dna2b9m2bdvCum2PS3T+ceDAgbDuJO9HWers6Ht2eno6rDvqdMirwxpdZnZc0quS3pJ01t2vL6kHAAAA4NJSNIDousndT9XWEgAAAACtxzMQAAAAAIqVDiBc0uNmdtjM7q76AzO728wOmdmh0TUPAAAAQJuU3sJ0o7ufNLMrJT1hZs+5+5PL/8Dd90jaI7XzIS0AAAAAwyu6AuHuJ7u/X5G0T9INdTYKAAAAQDulAwgzu8zM3nXu35JukfR03Q0DAAAA0D4ltzBdJWlfd56E1ZIedPfHam0VzhPluc5y80c5hdesWVPbeschyhOdyXKHR86cOTNw3VHI8kRHeeizeQei+TEyWd7/pkXbPGv7pk2bBl7vMDEdhyguWV+LPtvU1FRYN8pn3rTo2NL27VmnaG6B7Dshimk2f06Wu79p0T6UfU9lnz3S9DE32xei7Zb1l61bt/YtW1paCutm82c0LdqPsmNutM2zeSAWFhbC8ouVDiDc/ZikuFUAAAAAVgTSuAIAAAAoxgACAAAAQDEGEAAAAACKMYAAAAAAUIwBBAAAAIBi5j76SaOHmYm6jvaU6KapHYi7p5WHiUmU7ixL2xXJUqFFKdqyVKYlMZHiuGQp4qK4ZClqI/Pz82F5lHZvHHHJ0gJGKeyGicv+/fvD8mHSEY4iLln6u6i/ZClHI1lcorS64+gvmSgt4DBx2blzZ1g+MzMz8LLrPuZGKWaHSek7OzsblkfpHTPj6Ct1fRe1/Zibpf0+cuRIySoqRd/DWarjpo8t2TE32sejNK2StLi42Lcs+64ZJs38OPajaLvNzc0Nutixf0dzBQIAAABAMQYQAAAAAIoxgAAAAABQjAEEAAAAgGIMIAAAAAAUYwABAAAAoBgDCAAAAADF6poH4vuSziXxvULSqZGvZDijbNOUu79nRMsCAAAAWq2WAcR5KzA75O7X17qSi9TGNgEAAACTgFuYAAAAABRjAAEAAACg2DgGEHvGsI6L1cY2AQAAAK1X+zMQAAAAAC4d3MIEAAAAoFitAwgzu9XM/sPMXjCzP6xzXaXM7LiZfcfMjprZoabbAwAAAEyS2m5hMrNVkp6XdLOkE5KekvQJd3+2lhWWt+u4pOvdvW1zUwAAAACtV+cViBskveDux9z9DUkPSdpS4/oAAAAA1KzOAcQ1kl5e9vpE972muaTHzeywmd3ddGMAAACASbK6xmVbxXttSPl0o7ufNLMrJT1hZs+5+5NNNwoAAACYBHVegTgh6dplr98r6WSN6yvi7ie7v1+RtE+dW60AAAAAFKhzAPGUpPeZ2Xoz+0lJH5f05RrXlzKzy8zsXef+LekWSU832SYAAABgktR2C5O7nzWzeyR9XdIqSfe7+zN1ra/QVZL2mZnU+ewPuvtjzTYJAAAAmBzMRA0AAACgGDNRAwAAACjGAAIAAABAMQYQAAAAAIoxgAAAAABQjAEEAAAAgGIMIAAAAAAUYwABAAAAoBgDCAAAAADF/h9miw57cjmbVgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 792x144 with 11 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.datasets import load_digits\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.model_selection import train_test_split\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import sys\n",
    "import time\n",
    "\n",
    "\n",
    "def progress_bar(i):\n",
    "    '''持续调用此函数，并传入i，就可以显示基于i的进度的进度条'''\n",
    "    print(\"\\r\", end=\"\")  # 输出位置回到行首\n",
    "\n",
    "    # 显示进度百分比，并同时显示进度1/2(可以自己调节)个数的进度条符号：▋\n",
    "    print(\"计算最优K值: {}%: \".format(i), \"▋\" * (i // 2), end=\"\")\n",
    "    \n",
    "    # 有的时候大循环中printout不会马上运行，而是等代码运行结束后再依次运行\n",
    "    # 这样有可能让我们的进度条显示异常，所以\n",
    "    # 用flush强制输出,确保以上print语句运行\n",
    "    sys.stdout.flush()  \n",
    "\n",
    "# 提示：有的时候直接看函数可能不太好理解，这个时候就可以先看看下面的使用环境，结合应用再看函数定义就会更好理解了\n",
    "# 该函数通过X和y获得对应最大准确率的K，返回值包括：\n",
    "# max_acc -> 最大准确率\n",
    "# max_k -> 对应最大准确率的K\n",
    "# 整体用时 -> duration\n",
    "def get_max_K(X_train, X_test, y_train, y_test):\n",
    "    start = time.time()\n",
    "    max_k=0\n",
    "    max_acc=0\n",
    "    # 一共只有10个数字类别，所以没有必要让K能够达到两个类别，所以K最大就是总样本量//10\n",
    "    rg=(X_train.shape[0]//10)+1\n",
    "    for K in range(10,rg): # 为了保证代码演示效果，设置初始值为10\n",
    "        progress_bar(((K+1)*100)//rg)\n",
    "        knn = KNeighborsClassifier(n_neighbors=K)\n",
    "        knn.fit(X_train, y_train)\n",
    "        acc=knn.score(X_test,y_test)\n",
    "        if acc > max_acc:\n",
    "            max_acc=acc\n",
    "            max_k=K\n",
    "    end = time.time()\n",
    "    duration=end-start\n",
    "    return max_acc, max_k,duration\n",
    "\n",
    "# 1. 获取X和y\n",
    "df = load_digits(as_frame=True).frame\n",
    "X = df.drop('target', axis=1)\n",
    "y = df['target']\n",
    "\n",
    "# 2. train_test_split\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30)\n",
    "\n",
    "# 3. 创建KNN模型\n",
    "max_acc,K,duration = get_max_K(X_train, X_test, y_train, y_test)\n",
    "print(\"\\n当K=\", K, \"的时候此knn模型的准确率最高，为:\", max_acc,\"用时: {0:.2f}秒\".format(duration))\n",
    "knn = KNeighborsClassifier(n_neighbors=K) \n",
    "knn.fit(X_train, y_train)\n",
    "\n",
    "# 4. 获得算法的准确率\n",
    "acc = knn.score(X_test, y_test)\n",
    "\n",
    "# 制作一个3的图像\n",
    "d = np.array(\n",
    "    [[0, 0, 255, 255, 255, 255, 0, 0],\n",
    "     [0, 0,  0,  0,  0, 255, 0, 0],\n",
    "     [0, 0,  0,  0,  0, 255, 0, 0],\n",
    "     [0, 0,  0, 255, 255, 255, 0, 0],\n",
    "     [0, 0,  0,  0,  0, 255, 0, 0],\n",
    "     [0, 0,  0,  0,  0, 255, 0, 0],\n",
    "     [0, 0,  0,  0,  0, 255, 0, 0],\n",
    "     [0, 0, 255, 255, 255, 255, 0, 0]]\n",
    ")\n",
    "\n",
    "fg,ax=plt.subplots(1,K+1,figsize=(K+1,2))\n",
    "ax[0].imshow(d, cmap='gray')\n",
    "ax[0].set_title(str(knn.predict([d.ravel()])), size=20)\n",
    "\n",
    "_, index = knn.kneighbors([d.ravel()])  # 用模型获得该点的所有邻居按距离排序的的索引值列表index\n",
    "for i in range(0, K):\n",
    "    NN = X_train.iloc[index[0, i]]  # 获得第i个邻居\n",
    "    NN_label = y_train.iloc[index[0, i]] # 获得第i个邻居的标签\n",
    "    ax[i+1].imshow(NN.values.reshape(8,8), cmap='gray')\n",
    "    ax[i+1].set_title(str(NN_label), size=20)\n",
    "    ax[i+1].axis('off')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
